/********************************************************
 * Name: Stephen Durfey
 * Class: CS335
 * Date: October 6, 2008
 * File: sandwich.cpp
 * Description: This simple program creates a line queue for a sandwich
 * shop. Once the queue becomes full, expandQ() is called, and the size of the
 * queue is doubled to accommodate additional customers. 
 *********************************************************/

#include <iostream>
#include <sstream>
using namespace std;
const int initialSize = 5;


struct Order {

	string sandwich;
	string customerName;
	int orderNbr;
	bool fries;
};


class SandwichQueue{

public:

	SandwichQueue();
	
	//Interface for queue
	Order pop();
	void push(const Order& sandwich);
	void expandQ();
	bool isEmpty();
	int size();	

private:

	//qSize is size of array, not amount stored in queue
	int qSize;
	Order* orderQ;
	int front;
	int back;
	
};

int main()
{

	SandwichQueue sQ;

	Order testCases[15];
	Order temp;

	string s = "sandwich";
	string c = "customer";

	for(int i = 0; i < 15; i++)
	{
		
		testCases[i].sandwich = s;
		testCases[i].customerName = c;
		testCases[i].orderNbr = i;
		testCases[i].fries = i%2;
	}



	//a few tests...

	//add one
	sQ.push(testCases[0]);

	//remove one
	testCases[0] = sQ.pop();
        //cout << newO.customerName;


	//Next test wrap around
	for(int i = 0; i < 3; i++)
	{
		sQ.push(testCases[i]);
		sQ.push(testCases[i]);
		temp = sQ.pop();

	}
        
        //test undrflow
	for(int i = 0; i < 11; i++)
	{
		if(!sQ.isEmpty())
                {
                    temp = sQ.pop();
                }
		else
                    cout << "Q empty - no more sandwiches" << endl;
	}

	//test overflow
	for(int i = 0; i < 15; i++)
	{
		sQ.push(testCases[i]);
	}
	
}

SandwichQueue::SandwichQueue()
{
	qSize = initialSize;
	orderQ = new Order[initialSize];
	back = qSize - 1;
	front = qSize - 1;
}

bool SandwichQueue::isEmpty()
{
	if (front == back)
		return true;
	else
		return false;
}


int SandwichQueue::size()
{

	return (back - front + 1 + qSize) % qSize;

}

//function to pop
Order SandwichQueue::pop()
{
    if(!isEmpty())
    {
        front = (front + 1) % qSize;
        return orderQ[front];
    }
}

//push an element, make sure it is not full, if it is call expand funciton
void SandwichQueue::push(const Order& sw)
{
    if((back + 1) % qSize == front)
    {
        expandQ();
    }
    
    back = (back + 1) % qSize;
    orderQ[back] = sw;
}

//Double the queue size, copy the values, and reset back and front
void SandwichQueue::expandQ()
{
    int newSize = qSize * 2;
    Order* tempArray = new Order[newSize];
    int index;
    
    for(index = 0; front != back; index++)
    {
        tempArray[index] = orderQ[front];
        front = (front + 1) % qSize;
    }
    
    front = 0;
    back = index;
    orderQ = tempArray;
    qSize = newSize;
}



